﻿using System;
using UFIDA.U9.Cust.Pub.WebSocketSharp;
using UFIDA.U9.Cust.Pub.WebSocketSharp.Server;
using UFSoft.UBF.Util.Log;

namespace UFSoft.UBF.Cust.ClassView.MVC.WebSocket
{
    /// <summary>
    ///     WebSocket服务器管理类
    /// </summary>
    public sealed class WebSocketServerManager : IDisposable
    {
        internal const int ServerPort = 54188;
        private static WebSocketServerManager _instance;
        private static readonly object Lock = new object();
        private static readonly object InitLock = new object();
        private static readonly ILogger Logger = LoggerManager.GetLogger(typeof(WebSocketServerManager));
        private bool _disposed;
        private bool _isInited;
        private WebSocketServer _server;

        private WebSocketServerManager()
        {
        }

        public static WebSocketServerManager Instance
        {
            get
            {
                if (_instance != null)
                {
                    if (!_instance._isInited)
                    {
                        _instance.Init();
                    }

                    return _instance;
                }

                lock (Lock)
                {
                    if (_instance == null)
                    {
                        _instance = new WebSocketServerManager();
                        _instance.Init();
                    }
                    else if (!_instance._isInited)
                    {
                        _instance.Init();
                    }

                    return _instance;
                }
            }
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        ///     初始化
        /// </summary>
        public void Init()
        {
            lock (InitLock)
            {
                if (_isInited) return;
                Logger.Debug("WebSocketServerManager init...");
                try
                {
                    if (_server == null)
                    {
                        _server = new WebSocketServer(ServerPort);
                        _server.Log.Level = LogLevel.Debug;
                        _server.Log.Output = OutputLog;
                    }

                    if (!_server.IsListening)
                    {
                        _server.Start();
                    }

                    if (_server.IsListening)
                        Logger.Error("ws listening on port {0}", _server.Port);
                    //添加调试服务
                    _server.AddWebSocketService<TransactionDebugBehavior>(TransactionDebugBehavior.Path);
                    //添加代理服务
                    _server.AddWebSocketService<ProxyDoDebugBehavior>(ProxyDoDebugBehavior.Path);
                }
                catch (InvalidOperationException)
                {
                    if (_server != null)
                    {
                        _server.Stop();
                        _server = null;
                    }

                    throw;
                }

                _isInited = true;
            }
        }

        private static void OutputLog(LogData logData, string msg)
        {
            Logger.Error(logData.Message);
        }

        /// <summary>
        ///     添加服务宿主
        /// </summary>
        /// <param name="path"></param>
        public WebSocketServiceHost GetService(string path)
        {
            if (_server == null)
                throw new WebSocketException("WebSocket Server is null");
            WebSocketServiceHost host;
            _server.WebSocketServices.TryGetServiceHost(path, out host);
            return host;
        }

        /// <summary>
        ///     停止
        /// </summary>
        public void Stop()
        {
            if (_server == null) return;
            _server.Stop();
        }

        /// <summary>
        ///     析构函数
        /// </summary>
        ~WebSocketServerManager()
        {
            Dispose(false);
        }

        private void Dispose(bool disposing)
        {
            if (_disposed == false)
            {
                //Clean up unmanaged resources  
                Stop();
                if (disposing)
                {
                    //Clean Up managed resources  
                    _isInited = false;
                    _server = null;
                    _instance = null;
                }
            }

            _disposed = true;
        }
    }
}